package com.xjd.edu.admin.controller.login.auth;

import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.Lists;
import com.xjd.edu.admin.service.ISysUserService;
import com.xjd.edu.admin.service.impl.SysRecordLogService;
import com.xjd.edu.common.UserConstants;
import com.xjd.edu.common.admin.constant.Constants;
import com.xjd.edu.common.admin.domain.admin.LoginUser;
import com.xjd.edu.common.admin.domain.admin.SysUser;
import com.xjd.edu.common.admin.utils.DateUtils;
import com.xjd.edu.common.admin.utils.ip.IpUtils;
import com.xjd.edu.common.enums.HostTypeEnum;
import com.xjd.edu.common.enums.RedisKeyEnum;
import com.xjd.edu.common.enums.UserStatus;
import com.xjd.edu.common.exception.ServiceException;
import com.xjd.edu.common.model.login.LoginModel;
import com.xjd.edu.common.model.login.LoginResult;
import com.xjd.edu.common.utils.GenIdUtil;
import com.xjd.edu.common.utils.StringUtils;
import com.xjd.edu.toolkit.cache.GameRedisTemplate;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zsw
 * @description:
 * @date 2021-01-14 18:03:09
 */
@Component
@Slf4j
public class SystemAdminAuthentication extends AbsAuthentication {

    private static final String SESSION_CAPTCHA = "captcha";
    private static final int LOGIN_EXPIRE = 60 * 60;

    @Autowired
    private GameRedisTemplate gameRedisTemplate;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private SysRecordLogService recordLogService;

    @Value("${config.evn.prefix}")
    private String pre;

    @Override
    public List<HostTypeEnum> type() {
        return Lists.newArrayList(HostTypeEnum.PIPI_ADMIN);
    }

    @SneakyThrows
    @Override
    public LoginResult login(LoginModel loginModel, HostTypeEnum hostTypeEnum) {

        /*String password = loginModel.getPassword();
        String username = loginModel.getUsername();
        String code = loginModel.getCode();
        int times = 0;
        //password = Base64.decodeStr(password);
        String timesStr = (String) gameRedisTemplate.get(generateKey(RedisKeyEnum.ADMIN_CAPTCHA_TIMES, username)).orElse(null);
        if (timesStr != null) {
            times = Integer.parseInt(timesStr);
        }
        if (times >= 3) {
            String captcha = (String) gameRedisTemplate.get(SESSION_CAPTCHA).orElse(null);
            log.info("用户验证码code:{}", code);
            log.info("服务器验证码sessionCode:{}", captcha);
            // 判断验证码
            if (code == null || !code.trim().equalsIgnoreCase(captcha)) {
                throw new LoginException(LoginException.ExceptionCode.VERIFY_CODE_ERROR);
            }
        }
        if (times >= 10) {
            throw new LoginException(LoginException.ExceptionCode.ADMIN_LOGIN_LIMIT);
        }

        //通过username从数据库中查找 User对象，如果找到，没找到.
        SysUser admin = sysUserService.selectUserByUserName(username);
        log.info("adminInfo=" + admin);
        if (admin == null) {
            throw new LoginException(LoginException.ExceptionCode.ADMIN_NOT_EXITS);
        }
        if (AdminStatus.DISABLE.getType().equals(admin.getStatus())) {
            throw new LoginException(LoginException.ExceptionCode.ADMIN_FORBID);
        }
        *//*String salt = admin.getSalt();
        Password paramPassword = EncryptUtil.PiecesEncode(password, salt);

        log.info("decodePass:{},param pass:{},dbPass:{}", password, paramPassword, admin.getPassword());

        if (!Objects.equals(admin.getPassword(), paramPassword.getPassword())) {
            throw new LoginException(LoginException.ExceptionCode.ADMIN_PASSWORD_NOT_MATCH);
        }*//*
         *//*if (!Objects.equals(admin.getPassword(), password)) {
            throw new LoginException(LoginException.ExceptionCode.ADMIN_PASSWORD_NOT_MATCH);
        }*//*

        admin.setPassword(null);
        //admin.setSalt(null);
        Map<String, Object> adminMap = new HashMap<>();
        adminMap.put("id", admin.getUserId());
        adminMap.put("name", admin.getUserName());
        adminMap.put("username", admin.getUserName());
        //adminMap.put("status", admin.getStatus());
        adminMap.put("status", 0);
        String token = GenIdUtil.GetToken();
        gameRedisTemplate.hmset(generateKey(RedisKeyEnum.ADMIN_TOKEN, token), adminMap, Duration.ofSeconds(LOGIN_EXPIRE));


        LoginResult result = new LoginResult();
        BeanUtils.copyProperties(admin, result);
        result.setToken(token);
        gameRedisTemplate.del(generateKey(RedisKeyEnum.ADMIN_TOKEN, username));
        result.setMobile(DesensitizedUtil.mobilePhone(result.getMobile()));
        return result;*/
        String password = loginModel.getPassword();
        String username = loginModel.getUsername();
        String code = loginModel.getCode();
        LoginUser loginUser = login(username, password);

        String token = GenIdUtil.GetToken();
        Long userId = loginUser.getSysUser().getUserId();
        String userName = loginUser.getSysUser().getUserName();
        loginUser.setToken(token);
        loginUser.setUserid(userId);
        loginUser.setUsername(userName);
        loginUser.setIpaddr(IpUtils.getIpAddr());

        Map<String, Object> map = JSONObject.parseObject(JSONObject.toJSONString(loginUser), Map.class);
        map.put("id", loginUser.getSysUser().getUserId());
        map.put("name", loginUser.getSysUser().getUserName());
        map.put("username", loginUser.getSysUser().getUserName());
        map.put("status", 0);
        gameRedisTemplate.hmset(generateKey(RedisKeyEnum.ADMIN_TOKEN, loginUser.getToken()), map, Duration.ofSeconds(LOGIN_EXPIRE));

        LoginResult result = new LoginResult();
        BeanUtils.copyProperties(loginUser, result);
        result.setToken(token);
        gameRedisTemplate.del(generateKey(RedisKeyEnum.ADMIN_TOKEN, username));
        return result;
    }

    public String generateKey(RedisKeyEnum redisKeyEnum, String id) {
        return pre + RedisKeyEnum.SPLIT + redisKeyEnum.name() + RedisKeyEnum.SPLIT + id;
    }


    public LoginUser login(String username, String password) {
        // 用户名或密码为空 错误
        if (StringUtils.isAnyBlank(username, password)) {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写");
            throw new ServiceException("用户/密码必须填写");
        }
        // 密码如果不在指定范围内 错误
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围");
            throw new ServiceException("用户密码不在指定范围");
        }
        // 用户名不在指定范围内 错误
        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围");
            throw new ServiceException("用户名不在指定范围");
        }
        // IP黑名单校验
        /*String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST));
        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾，访问IP已被列入系统黑名单");
            throw new ServiceException("很遗憾，访问IP已被列入系统黑名单");
        }*/
        // 查询用户信息
        LoginUser userInfo = sysUserService.getLoginUserInfo(username);
        if (StringUtils.isNull(userInfo)) {
            throw new ServiceException("系统内部错误，请联系管理员！");
        }

        //LoginUser userInfo = userResult.getData();
        SysUser user = userInfo.getSysUser();
        if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起，您的账号已被删除");
            throw new ServiceException("对不起，您的账号：" + username + " 已被删除");
        }
        if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用，请联系管理员");
            throw new ServiceException("对不起，您的账号：" + username + " 已停用");
        }
        //passwordService.validate(user, password);
        recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
        recordLoginInfo(user.getUserId());
        return userInfo;
    }

    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    public void recordLoginInfo(Long userId) {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        // 更新用户登录IP
        sysUser.setLoginIp(IpUtils.getIpAddr());
        // 更新用户登录时间
        sysUser.setLoginDate(DateUtils.getNowDate());
        sysUserService.updateUserProfile(sysUser);
    }
}
